/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin			*/
/*	Project:					*/
/*	Author:		gong_libin			*/
/*	Date:		2011_09_22			*/
/*	File:		GlbArea.cpp			*/
/********************************************************/

#include "GlbArea.h"

CGlbArea::CGlbArea()
{
	m_puszArea = NULL;
}

CGlbArea::~CGlbArea()
{
	if (NULL != m_puszArea) {
		free(m_puszArea);
		m_puszArea = NULL;
	}
}

void CGlbArea::GlbAreaDestory()
{
	if (NULL != m_puszArea) {
		free(m_puszArea);
		m_puszArea = NULL;
	}

	return;
}

int CGlbArea::GlbAreaInit(char* pszFile)
{
	FILE* fp = NULL;
	ULONG ulSize = 0;
	int iReturn = GLB_SUCCESS;

	fp = fopen(pszFile, "rb");
	if (NULL == fp) {
		GLB_ERROR("%s\n", strerror(errno));
		return GLB_FAILURE;
	}

	fseek(fp, 0L, SEEK_END);
	ulSize = ftell(fp);
	rewind(fp);

	m_puszArea = (UCHAR*)malloc(sizeof(UCHAR) * ulSize);
	if (NULL != m_puszArea) {
		memset(m_puszArea, '\0', sizeof(UCHAR) * ulSize);
		fread(m_puszArea, sizeof(UCHAR), sizeof(UCHAR) * ulSize, fp); 
	}
	else {
		iReturn = GLB_FAILURE;
	}

	fclose(fp);

	return iReturn;
}

void CGlbArea::GlbAreaCheck(char* pszIP, char* pszArea)
{
	ULONG ulIP = 0;
	ULONG ulEnd = 0;
	ULONG ulStart = 0;
	ULONG ulCurrent = 0;
	char szCountry[BUFFER_SIZE] = { 0 };
	char szLocation[BUFFER_SIZE] = { 0 };

	ulIP = GlbAreaGetIP(pszIP);
	GlbAreaGetHead(&ulStart, &ulEnd);
	ulCurrent = GlbAreaSearch(ulStart, ulEnd, ulIP);
	GlbAreaGetAddress(GlbAreaGetValue(ulCurrent + 4, 3), szCountry, szLocation);
	sprintf(pszArea, "%s[%s]", szCountry, szLocation);

	return;
}

int CGlbArea::GlbAreaBeNumber(char cVal)
{
	int iReturn = 1;

	if (cVal >= '0' && cVal <= '9') {
		iReturn = 0;
	}

	return iReturn;
}

ULONG CGlbArea::GlbAreaGetIP(char* pszIP)
{
	int iTemp = 0;
	ULONG ulIP = 0;
	UINT uiCount = 0;

	for (uiCount = 0; uiCount < strlen(pszIP); uiCount ++) {
		if ('.' == *(pszIP + uiCount)) {
			ulIP = ulIP * 0x100 + iTemp;
			iTemp = 0;
		}
		else {
			if (GlbAreaBeNumber(0 == *(pszIP + uiCount))) {
				iTemp = iTemp * 10 + *(pszIP + uiCount) - '0';
			}
			else {
				return 0;
			}
		}
	}

	ulIP = ulIP * 0x100 + iTemp;

	return ulIP;
}

ULONG CGlbArea::GlbAreaGetValue(ULONG ulStart, int iLength)
{
	int iCount = 0;
	ULONG ulVariable = 0;
	ULONG ulVal[iLength];
	UCHAR* puszCurrent = NULL;

	puszCurrent = m_puszArea + ulStart;
	for (iCount = 0; iCount < iLength; iCount ++) {
		ulVal[iCount] = *(puszCurrent + iCount) & 0x000000ff;
	} 

	for (iCount = iLength - 1; iCount >= 0; iCount --) {
		ulVariable = ulVariable * 0x100 + ulVal[iCount];
	}

	return ulVariable;
}

void CGlbArea::GlbAreaGetHead(ULONG* pulStart, ULONG* pulEnd)
{
	*pulStart = GlbAreaGetValue(0L, 4);
	*pulEnd = GlbAreaGetValue(4L, 4);

	return;
}

ULONG CGlbArea::GlbAreaGetString(ULONG ulStart, char* pszValue)
{
	ULONG ulCount = 0;
	UCHAR* puszCurrent = m_puszArea + ulStart;

	do {
		*(pszValue + ulCount) = *(puszCurrent + ulCount);
		ulCount += 1;
	} while ('\0' != *(puszCurrent + ulCount));

	return ulCount;
}

ULONG CGlbArea::GlbAreaSearch(ULONG ulStart, ULONG ulEnd, ULONG ulIP)
{
	ULONG ulRecord = 0;
	ULONG ulCurrent = 0;
	ULONG ulTop = ulEnd;
	ULONG ulBottom = ulStart;

	ulCurrent = ((ulTop - ulBottom) / 7 / 2) * 7 + ulBottom;
	do {
		ulRecord = GlbAreaGetValue(ulCurrent, 4);
		if (ulRecord > ulIP) {
			ulTop = ulCurrent;
			ulCurrent = ((ulTop - ulBottom) / 14) * 7 + ulBottom;
		}
		else {
			ulBottom = ulCurrent;
			ulCurrent = ((ulTop - ulBottom) / 14) * 7 + ulBottom;
		}
	} while (ulBottom < ulCurrent);

	return ulCurrent;
}

void CGlbArea::GlbAreaGetAddress(ULONG ulStart, char* pszCountry, char* pszLocation)
{
	ULONG ulRedir = 0;
	ULONG ulCountry = 0;
	ULONG ulLocation = 0;
	UCHAR* puszCurrent = NULL;

	ulStart += 4;
	puszCurrent = m_puszArea + ulStart;

	if (GLB_REDIR_1 == (*puszCurrent & 0x000000ff)) {
		ulRedir = GlbAreaGetValue(ulStart + 1, 3);
		puszCurrent = m_puszArea + ulRedir;
		if (GLB_REDIR_2 == (*puszCurrent & 0x000000ff)) {
			ulCountry = GlbAreaGetValue(ulRedir + 1, 3);
			ulLocation = ulRedir + 4;
			GlbAreaGetString(ulCountry, pszCountry);
		}
		else {
			ulCountry = ulRedir;
			ulLocation = ulRedir + GlbAreaGetString(ulCountry, pszCountry);
		}
	}
	else if (GLB_REDIR_2 == (*puszCurrent & 0x000000ff)) {
		ulCountry = GlbAreaGetValue(ulStart + 1, 3);
		ulLocation = ulStart + 4;
		GlbAreaGetString(ulCountry, pszCountry);
	}
	else {
		ulCountry = ulStart;
		ulLocation = ulCountry + GlbAreaGetString(ulCountry, pszCountry);
	}

	puszCurrent = m_puszArea + ulLocation;
	if (GLB_REDIR_1 == (*puszCurrent & 0x000000ff) || GLB_REDIR_2 == (*puszCurrent & 0x000000ff)) {
		ulLocation = GlbAreaGetValue(ulLocation + 1, 3);
	}
	GlbAreaGetString(ulLocation, pszLocation);

	return;
}
